﻿using System;
using System.Collections.Generic;
using System.Text;
using KingSite.Library.Sms;
using KingSite.Library.Tools;
using System.Net;
using System.IO;
using System.Configuration;
using KingSite.Library.Mail;
using System.Diagnostics;
using System.Threading;

namespace KingSite.SiteWatcher {
    class Program {
        static string fileName = string.Format("{0}/watcher.txt", AppDomain.CurrentDomain.BaseDirectory);
        static string url = ConfigurationManager.AppSettings["SiteUrl"];
        static string exInfo = ConfigurationManager.AppSettings["ExInfo"];
        static int FailedCount = int.Parse(ConfigurationManager.AppSettings["FailedCount"]);
        static bool IsResetIIS = bool.Parse(ConfigurationManager.AppSettings["IsResetIIS"]);
        static string mobile = ConfigurationManager.AppSettings["moblie"];
        static string mailWatcherEmail = ConfigurationManager.AppSettings["MailWatcherEmail"];

        static IMail mail = MailHelper.GetInstance();
        static ISms sms = SmsHelper.GetInstance();

        static void Main(string[] args) {
            
            string url2 = string.Format("http://{0}", url);
            int respTimeSpan = 0;
            HttpStatusCode status = GetSiteStatus(url2, out respTimeSpan);
            Thread.Sleep(10);//间隔10秒后重试
            HttpStatusCode status2 = GetSiteStatus(url2, out respTimeSpan);
            //连续尝试2次后，都返回错误，则一定是发生了异常
            if (status != HttpStatusCode.OK && status2 != HttpStatusCode.OK) {
                SetFaildStatus(status);
            }
            else {
                SetOKStatus();
            }

        }

        private static HttpStatusCode GetSiteStatus(string url, out int respTimeSpan) {
            HttpStatusCode result = HttpStatusCode.OK;
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "GET";
            req.Timeout = 15 * 1000; //15秒超时
            HttpWebResponse res;
            long startTicks = DateTime.Now.Ticks;
            respTimeSpan = 0;
            try {
                res = (HttpWebResponse)req.GetResponse();
                long endTicks = DateTime.Now.Ticks;
                result = res.StatusCode;
                TimeSpan ts = new TimeSpan(endTicks - startTicks);
                double tm = ts.TotalMilliseconds;
                respTimeSpan = Convert.ToInt32(tm);
            }
            catch (WebException ex) {
                res = (HttpWebResponse)ex.Response;
                if (res == null) {
                    result = HttpStatusCode.RequestTimeout;
                }
                else {
                    result = res.StatusCode;
                }
            }
             Console.WriteLine("StautsCode:" + result.ToString());
             return result;
        }

        private static int ReadStatus(out int count) {
            int result = 200;
            count = 0;            
            if (File.Exists(fileName)) {
                string content = File.ReadAllText(fileName);
                string[] cs = content.Split(';');
                result = Convert.ToInt32(cs[0]);
                count = Convert.ToInt32(cs[1]);
            }
            return result;
        }

        private static void WriteStatus(HttpStatusCode statusCode, int count) {
            string content = string.Format("{0};{1}", (int)statusCode, count);
            File.WriteAllText(fileName, content);
        }

        private static void SetOKStatus() {
            bool b = false;
            //先读取文件当前的状态
            int count = 1;
            int code = ReadStatus(out count);
            //如果文件里面的状态不是200，则表示是从失败状态转换到OK状态，要发送提醒信息
            if (code != 200) {
                b = true;
            }
            //写入OK状态
            WriteStatus(HttpStatusCode.OK, 1);
            if (b) {
                //发送OK短信
                SendOKSms();
                //发送Email
                SendOKEmail();
            }
            
        }

        private static void SetFaildStatus(HttpStatusCode statusCode) {
            //先读取文件当前的状态
            int count = 1;
            int code = ReadStatus(out count);
            if ((code != 200) && (code == (int)statusCode)) {
                count++;
            }
            //写入失败状态
            WriteStatus(statusCode, count);
            //发送失败信息
            if (count < FailedCount) {
                SendAlertSms(statusCode);
                SendAlertEmail(statusCode);
            }
            //超出失败次数后，重启IIS
            else if(IsResetIIS) { 
                //重启IIS
                ResetIIS();
            }
        }

        private static void SendAlertSms(HttpStatusCode statusCode) {            
            string message = GetErrorMsg(statusCode);
            SendSms(mobile, message);       
        }

        private static void SendOKSms() {
            string message = GetOKMsg();
            SendSms(mobile, message);
        }

        private static void SendSms(string mobile, string message) {            
            
            string[] mobiles = mobile.Split(',');
            foreach (string m in mobiles) {
                sms.Send(m, message);
                Thread.Sleep(5);
            }
        }

        private static string GetOKMsg() {
            string message = string.Format("{0} 于 {1} 恢复可用！200 OK，{2}", url, DateTime.Now, exInfo);
            return message;
        }

        private static string GetErrorMsg(HttpStatusCode statusCode) {
            string message = string.Format("{0} 于 {1} 发生错误:{2}[{3}]，{4}", url, DateTime.Now, (int)statusCode, statusCode.ToString(), exInfo);
            return message;
        }

        private static void GetMail() {
            mail.Server = ConfigurationManager.AppSettings["MailServer"];
            mail.SenderAddress = ConfigurationManager.AppSettings["MailSenderAddress"];
            mail.Username = ConfigurationManager.AppSettings["MailUsername"];
            mail.Password = ConfigurationManager.AppSettings["MailPassword"];
        }

        private static void SendAlertEmail(HttpStatusCode statusCode) {
            string message = GetErrorMsg(statusCode);
            SendEmail(message);
        }

        private static void SendOKEmail() {                        
            string message = GetOKMsg();
            SendEmail(message);
        }

        private static void SendEmail(string message) {
            GetMail();
            string[] emails = mailWatcherEmail.Split(',');
            foreach (string toAddress in emails) {
                mail.Send(toAddress, message, message, false);
                Thread.Sleep(5);
            }
        }

        private static void ResetIIS() {
            ProcessStartInfo ps = new ProcessStartInfo("iisreset");
            ps.UseShellExecute = false;
            ps.RedirectStandardOutput = true;
            Process p = Process.Start(ps);
            p.WaitForExit();
            string output = p.StandardOutput.ReadToEnd();
            Console.WriteLine(output);
        }

    }
}
